package pers.sakurasora.changeoveramount;

import pers.sakurasora.changeoveramount.util.InputFormatUtil;

/**
 * @FileName AmountConversion.java
 * @author SakuraSora
 * @Email 1468071675@qq.com
 * @DateTime 2019年1月16日 上午11:34:53
 *
 * @Description 
 * 				<p>金额转换：数字金额转大写。（金额可以是整数也可以是小数；小数部分两位数，整数部分最大长度为16位）</p>
 * 				 <p>转换规则：<br>
 * 							中文大写金额数字到"元"为止的，在"元"之后，应写"整"(或"正")字。<br>
 * 							在"角"之后，可以不写"整"(或"正")字。大写金额数字有"分"的，"分"后面不写"整"(或"正")字。<br>
 * 							中文大写金额数字前应标明"人民币"字样。<br>
 * 							阿拉伯数字中间有"0"时，中文大写要写"零"字。<br>
 * 							阿拉伯数字中间连续有几个"0"时，中文大写金额中间可以只写一个"零"字。<br>
 * 							阿拉伯金额数字万位和元位是"0"；或者数字中间连续有几个"0"，万位、元位也是"0"，但千位、角位不是"0"时，中文大写金额中可以只写一个零字，也可以不写"零"字。<br>
 * 							阿拉伯金额数字角位是"0"，而分位不是"0"时，中文大写金额"元"后面应写"零"字。</p>
 */
public class AmountConversion {

	/**
	 * 存放大写金额数字0-9的字符串数组（常量）
	 */
	private final String[] UPPERCASE_NUMBERS = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
	/**
	 * 存放整数大写金额单位（元(圆)到千兆）的字符串数组（常量）
	 */
	private final String[] AMOUNT_IUNITS = { "元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "兆", "拾","佰", "仟" };
	/**
	 * 存放金额转换结果（大写金额）
	 */
	private String sAmountInWords;

	public AmountConversion() {

	}

	/**
	 * 获得金额转换结果
	 * @param sMoney 金额字符串
	 * @return 大写金额
	 * @throws Exception 
	 */
	public String getAmountInWords(String sMoney)
        throws Exception 
	{
		this.sAmountInWords = ""; // 转换结果

		if (InputFormatUtil.isMoneyNotEmpty(sMoney) == false || InputFormatUtil.moneyCheck(sMoney) == false) {
			return this.sAmountInWords;
		}
		/**
		 * 如果金额字符串包含小数点，分割整数与小数部分；否则转换整数部分并添加“整”字；<br>
		 * 包含小数点：<br>
		 * 			如果小数部分为0，转换整数后添加“整”字；<br>
		 * 			如果整数和小数部分都为0，转换结果为“人民币零元整”<br>
		 * 			否则，整数转换结果拼接小数转换结果<br>
		 * 最终结果开头要添加“人民币”
		 */
		if (sMoney.contains(".")) {
			String[] money = sMoney.split("\\.");
			if ((money[0].length() == 1 && Integer.parseInt(money[0]) == 0) && Integer.parseInt(money[1]) == 0) {
				this.sAmountInWords = "人民币" + "零元" + "整";
				return this.sAmountInWords;
			} else {
				if (!(money[0].length() == 1 && Integer.parseInt(money[0]) == 0)) {
					this.sAmountInWords += getIntegerAmountInWords(money[0]);
				}
				if (Integer.parseInt(money[1]) == 0) {
					this.sAmountInWords += "整";
					this.sAmountInWords = "人民币" + this.sAmountInWords;
					return this.sAmountInWords;
				}
				if (Integer.parseInt(money[1]) != 0) {
					this.sAmountInWords += getDecimalAmountInWords(money[1]);
					this.sAmountInWords = "人民币" + this.sAmountInWords;
					return this.sAmountInWords;
				}
			}
		}
		else {
			if (sMoney.length() == 1 && Integer.parseInt(sMoney) == 0) {
				this.sAmountInWords = "人民币" + "零元整";
			} else {
				this.sAmountInWords = "人民币" + getIntegerAmountInWords(sMoney) + "整";
			}
			return this.sAmountInWords;
		}
		return this.sAmountInWords;
	}

	/**
	 * 整数部分金额转换;不考虑0元
	 * @param sIntegerMoney 整数部分金额（小写）
	 * @return 整数部分大写金额
	 */
	private String getIntegerAmountInWords(String sIntegerMoney) {
		String sIntegerAmountInWords = "";
		int iNext;
	
		/**
		 * 遍历：
		 * 1、非0数字转大写并加上单位<br>
		 * 2、对0的处理（下标为i的字符为0）：<br>
		 * 		（1）如：100,0000,0001等中间的一组4个0不做任何处理，直接跳过<br>
		 * 		（2）“拾”位低一位为0， 不加“零”，直接加单位<br>
		 * 		（3）其他情况，0（当前i下标字符为0）遇非0时补“零”
		 */
		for (int i = 0, j = sIntegerMoney.length() - 1; i < sIntegerMoney.length(); i++, j--) {
			if (sIntegerMoney.charAt(i) != '0') {
				sIntegerAmountInWords += this.UPPERCASE_NUMBERS[sIntegerMoney.charAt(i) - '0'] + this.AMOUNT_IUNITS[j];
			}
			else {						
				if (i + 4 < sIntegerMoney.length() && this.AMOUNT_IUNITS[j].equals("仟") && sIntegerMoney.substring(i, i+4).equals("0000")) {
					i = i + 3; 
					j = j - 3;
					continue;
				}
				
				iNext = i + 1;
				if (iNext == sIntegerMoney.length()) {
					iNext = i;
				}
				
				if (this.AMOUNT_IUNITS[j + 1].equals("拾")) {
					sIntegerAmountInWords += this.AMOUNT_IUNITS[j];
				}
				else if (sIntegerMoney.charAt(iNext) != '0') {
					sIntegerAmountInWords += "零";
				}
			}
		}
		return sIntegerAmountInWords;
	}
	
	/**
	 * 小数部分金额转换 ：到“分”为止；不考虑0角0分<br>
	 * 效果如：0.09转换为 人民币玖分
	 * @param sDecimalMoney 小数部分金额（小写）
	 * @return 小数部分大写金额
	 */
	private String getDecimalAmountInWords(String sDecimalMoney) {
		String sDecimalAmountInWords = "";

		/**
		 * 1、阿拉伯金额数字角位不是‘0’，数字转大写并添加“角”<br>
		 * 2、如果存在“分”位，并且分位不是‘0’，数字转大写并添加“分”
		 */
		if (sDecimalMoney.length() > 0) {
			if (sDecimalMoney.charAt(0) != '0') {
				sDecimalAmountInWords += this.UPPERCASE_NUMBERS[sDecimalMoney.charAt(0) - '0'] + "角";
			}
			if (sDecimalMoney.length() > 1 && sDecimalMoney.charAt(1) != '0') {
				sDecimalAmountInWords += this.UPPERCASE_NUMBERS[sDecimalMoney.charAt(1) - '0'] + "分";
			}
		}
		return sDecimalAmountInWords;
	}

//	/**
//	 * 小数部分金额转换 ：到“分”为止；不考虑0角0分<br>
//	 * 效果如：0.09转换为 人民币零玖分
//	 * @param sDecimalMoney 小数部分金额（小写）
//	 * @return 小数部分大写金额
//	 */
//	private String getDecimalAmountInWords(String sDecimalMoney) {
//		String sDecimalAmountInWords = "";
//
//		/**
//		 * 1、阿拉伯金额数字角位不是‘0’，数字转大写并添加“角”<br>
//		 * 2、如果存在“分”位： 分位不是‘0’，数字转大写并添加“分”<br>
//		 * 如果“角”位是0并且“分“位不是0时，”分“位前写”零“字
//		 */
//		if (sDecimalMoney.length() > 0) {
//			if (sDecimalMoney.charAt(0) != '0') {
//				sDecimalAmountInWords += this.UPPERCASE_NUMBERS[sDecimalMoney.charAt(0) - '0'] + "角";
//			}
//			if (sDecimalMoney.length() > 1) {
//				if (sDecimalMoney.charAt(1) != '0') {
//					sDecimalAmountInWords += this.UPPERCASE_NUMBERS[sDecimalMoney.charAt(1) - '0'] + "分";
//					if (sDecimalMoney.charAt(0) == '0') {
//						sDecimalAmountInWords = "零" + sDecimalAmountInWords;
//					}
//				}
//
//			}
//		}
//		return sDecimalAmountInWords;
//	}
}
